﻿using Application.CommonDto;
using Application.RoleServices.Dto;
using Entity;
using Entity.BaseEntitys;
using Entity.RolePermissionss;
using EntityFrameWorkCore;
using FrameWorkCore;
using Repository.Repository;
using ShardingCore.Extensions.ShardingPageExtensions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Utility.Helper;

namespace Application.RoleServices
{
    public interface IRoleService
    {
    }

    public class RoleService: ApplicationServiceBase, IRoleService
    {
        public IRepository<RolePermissions,Guid, DefaultDbContext> RolePermissionsRep { get; set; }



        public async ValueTask CreateRole(CreateRoleDto dto)
        {

           if ((await RoleRep.FirstOrDefaultAsync(x => x.RoleName.Trim().ToLower().Equals(dto.RoleName.Trim().ToLower()))) is not null)
               throw new Exception("Role name already exists");
           var role = await base.RoleRep.InsertAsync(base.MapTo<Role>(dto));

            if (dto.RolePermissionsIds.Any())
                await RolePermissionsRep.BatchInsertAsync(dto.RolePermissionsIds.Select(x =>
                new RolePermissions 
                { 
                    Id = GuidExtension.NewGuid(), 
                    RoleId = role.Id,
                    PermissionsId = x 
                }).ToList());
        }



        public async ValueTask DeleteRole(EntityAreaDto<Guid> dto)
        {
            await RoleRep.DeleteAsync(x => x.Id == dto.Id && x.SplitArea == dto.SplitArea);
            await RolePermissionsRep.BatchDeleteAsync(x => x.RoleId == dto.Id);
        }

        public async ValueTask UpdateRole(UpdateRoleDto dto)
        {
            var role = await RoleRep.FirstOrDefaultAsync(x => x.Id == dto.Id && x.SplitArea == dto.SplitArea);
            base.Map(dto, role);
            await RoleRep.UpdateAsync(role);

            if (dto.RolePermissionsIds.Any())
            {
                await RolePermissionsRep.BatchDeleteAsync(x => x.RoleId == dto.Id);
                await base.UnitOfWorkManager.SaveActiveUnitOfWorkAsync();
                await RolePermissionsRep.BatchInsertAsync(dto.RolePermissionsIds.Select(x =>
                new RolePermissions
                {
                    Id = GuidExtension.NewGuid(),
                    RoleId = dto.Id,
                    PermissionsId = x
                }).ToList());
            }
            
        }


        public async ValueTask<ShardingPagedResult<RoleByPageOutDto>> GetRoleByPage(RoleByPageDto dto)
        {

                var all = base.RoleRep.GetAll()
                .QaWhereIf(!dto.RoleName.IsNullOrEmpty(), x => x.RoleName.Contains(dto.RoleName))
                .QaWhereIf(!dto.RoleDescribe.IsNullOrEmpty(), x => x.RoleDescribe.Contains(dto.RoleDescribe));

                var res = from item in all
                          select new RoleByPageOutDto
                          {
                              Id = item.Id,
                              RoleName = item.RoleName,
                              RoleDescribe = item.RoleDescribe,
                              CreateTime = item.CreateTime,
                              TimeStamp = item.TimeStamp,
                              SplitArea = item.SplitArea
                          };

                return await res.QaPagedResult(dto);
        }


        public async ValueTask<List<AllRoleDto>> GetAllRole()
            => (await base.RoleRep.GetAllListAsync()).Select(x => new AllRoleDto { Id = x.Id ,RoleName = x.RoleName  }).ToList();

        public async ValueTask<List<Guid>> GetRolePermissionsIds(EntityDto<Guid> dto)
         => (await RolePermissionsRep.GetAllListAsync(x => x.RoleId == dto.Id)).Select(x => x.PermissionsId).ToList();
    }
}
